package com.chenfan.mcn.component;

import com.alibaba.fastjson.JSONObject;
import com.chenfan.mcn.clients.DingTalkAlarmClient;
import com.chenfan.common.extension.util.wrapper.RunnableWrapper;
import com.chenfan.common.extension.util.SmartExecutorService;
import com.dingtalk.api.request.OapiRobotSendRequest;
import com.dingtalk.api.response.OapiRobotSendResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.util.concurrent.ExecutorService;

/**
 * @author wulg
 * @date 2023/10/19
 */
@Slf4j
@Component
public class DingTalkAlarmSender {

    @Autowired
    private DingTalkAlarmClient alarmClient;

    @Value("${alarm.dingtalk.secret:SEC8ce681fc96ce9f301d84542f18eba64d7ace559cc22fc572b1c6ad7ebc1221d7}")
    private String secret;

    @Value("${alarm.dingtalk.accessToken:fdb83c56077dfb5d08539ca762c244d13f16008d73f090e312dcb1f12f429e27}")
    private String accessToken;

    @Value("${alarm.kibnana.url: http://elk.thechenfan.cn/app/kibana#/discover?_g=(time:(from:now-1w,to:now))&_a=(columns:!(traceId,message),query:(language:kuery,query:'%s'),sort:!(!('@timestamp',desc)))}")
    private String kibnanaUrl;

    private static ExecutorService smartExecutorService = SmartExecutorService.newFixedThreadPool();

    private static final String DEFAULT_ENCODING = "UTF-8";

    private static final String ALGORITHM = "HmacSHA256";

    private static final String NEW_LINE = "\n";


    /**
     * 发送消息请求
     * @param sendRequest
     */
    public void send(OapiRobotSendRequest sendRequest) {
        try {
            smartExecutorService.submit(new RunnableWrapper(() -> {
                long timestamp = System.currentTimeMillis();
                sendRequest.setTimestamp(timestamp);
                OapiRobotSendResponse sendResponse = alarmClient.robotSend(accessToken, timestamp, getSign(timestamp), sendRequest);
                if(sendResponse.isSuccess()) {
                    if(log.isDebugEnabled()) {
                        log.debug("【钉钉机器人微告警】发送成功！请求：{}， 响应：{}", JSONObject.toJSONString(sendRequest),  JSONObject.toJSONString(sendResponse));
                    }
                } else {
                    log.error("【钉钉机器人微告警】发送失败！请求：{}， 响应：{}", JSONObject.toJSONString(sendRequest),  JSONObject.toJSONString(sendResponse));
                }
            }));
        } catch (Exception e) {
            log.error("【钉钉机器人微告警】发送异常！请求：{}", JSONObject.toJSONString(sendRequest), e);
        }
    }

    /**
     * 发送markdown消息
     * @param title
     * @param text
     */
    public void sendMarkdown(String title, String text) {
        this.send(this.buildMarkdownRequest(title, text));
    }

    /**
     *
     * @param title
     * @param text
     * @return
     */
    private OapiRobotSendRequest buildMarkdownRequest(String title, String text) {
        OapiRobotSendRequest sendRequest = new OapiRobotSendRequest();
        sendRequest.setMsgtype("markdown");
        OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
        markdown.setTitle(title);
        markdown.setText(text);
        sendRequest.setMarkdown(markdown);
        OapiRobotSendRequest.At at = new OapiRobotSendRequest.At();
        at.setIsAtAll(true);
        sendRequest.setAt(at);
        return sendRequest;
    }

    /**
     *
     * @param timestamp
     * @return
     */
    @SneakyThrows
    private String getSign(long timestamp) {
        String stringToSign = timestamp + NEW_LINE + secret;
        Mac mac = Mac.getInstance(ALGORITHM);
        mac.init(new SecretKeySpec(secret.getBytes(DEFAULT_ENCODING), ALGORITHM));
        byte[] signData = mac.doFinal(stringToSign.getBytes(DEFAULT_ENCODING));
        return URLEncoder.encode(new String(Base64.encodeBase64(signData)), DEFAULT_ENCODING);
    }

    /**
     *
     * @param traceId
     * @return
     */
    public String getSkipUrl(String traceId) {
        return String.format(kibnanaUrl, traceId);
    }
}
